package com.hjl.web.servlet;

import com.hjl.domain.Doc_User_inf;
import com.hjl.domain.Document_inf;
import com.hjl.domain.PageBean;
import com.hjl.domain.User_inf;
import com.hjl.service.DocumentService;
import com.hjl.service.impl.DocumentServiceImpl;
import com.hjl.util.DownLoadUtils;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 文件表现层
 * Servlet3.0后，使用@MultipartConfig注解
 * (1).处理文件上传的Servlet使用@MultipartConfig注解修饰；该Servlet主要完成访问上传页面以及处理文件上传，
 * 通过HttpServletRequest提供的getPart(String name)或getParts()方法获取到上传的文件，再使用Part相关的API
 * 获取文件信息以及完成上传。
 * (2).通过该注解提供的属性：maxFileSize、maxRequestSize等可以对上传文件大小、请求大小进行控制
 *
 * @author Lenovo
 * @version 1.0
 * @date 2021/10/8 20:51
 */
@WebServlet("/documents/*")
@MultipartConfig
public class DocumentServlet extends BaseServlet {
    private DocumentService documentService = new DocumentServiceImpl();
    String prefix = "/WEB-INF/jsp/document/";
    String suffix = ".jsp";

    /**
     * 跳转WEB-INF里的jsp
     */
    public void toList(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.getRequestDispatcher(prefix + "documentlist" + suffix).forward(req, resp);
    }

    public void toAdd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.getRequestDispatcher(prefix + "documentadd" + suffix).forward(req, resp);
    }

    public void toEdit(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.getRequestDispatcher(prefix + "documentedit" + suffix).forward(req, resp);
    }

    /**
     * 分页
     */
    public void findDocumentByPage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        //获取数据（当前页码和行数）
        String currentPage = req.getParameter("currentPage");
        String rows = req.getParameter("rows");
        //默认第1页，5行
        if (currentPage == null || "".equals(currentPage)) {
            currentPage = "1";
        }
        if (rows == null || "".equals(rows)) {
            rows = "5";
        }
        Map<String, String[]> condition = req.getParameterMap();
        PageBean<Doc_User_inf> pb = documentService.findDocumentByPage(currentPage, rows, condition);
        req.setAttribute("documents", pb);
        req.setAttribute("condition", condition);

        req.getRequestDispatcher("/documents/toList").forward(req, resp);
    }

    /**
     * 删除选中
     */
    public void delSelected(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        String path = req.getServletContext().getRealPath("file");

        String[] ids = req.getParameterValues("id");
        for (String id : ids) {
            Document_inf document = documentService.findDocumentById(id);
            String filename = document.getTemporaryfilename();
            String filePath = "file/" + filename;
            filePath = this.getServletContext().getRealPath(filePath);
            File delFile = new File(filePath);
            boolean flag = false;
            String msg = "";
            if (delFile.exists()) {
                flag = delFile.delete();
                if (flag) {
                    msg = "删除成功";
                } else {
                    msg = "删除失败";
                }
            } else {
                msg = "文件不存在";
            }
            resp.getWriter().print(msg);
        }
        documentService.delSelect(ids);
        resp.sendRedirect(req.getContextPath() + "/documents/findDocumentByPage");
    }

    /**
     * 查询单个（用于编辑）
     */
    public void findDocument(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取参数
        String id = req.getParameter("id");
        //调用service方法
        Document_inf document = documentService.findDocumentById(id);
        //存入request
        req.setAttribute("document", document);
        System.out.println(document);
        //转发到documentedit.jsp
        req.getRequestDispatcher("/documents/toEdit").forward(req, resp);
    }

    /**
     * 更新
     */
    public void updateDocument(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1、创建磁盘文件项工厂
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //2、创建文件上传的核心类
        ServletFileUpload upload = new ServletFileUpload(factory);
        //3、解析request---获得文件项集合
        List<FileItem> parseRequest = new ArrayList<>();
        try {
            parseRequest = upload.parseRequest(req);
        } catch (FileUploadException e) {
            e.printStackTrace();
        }

        String fileName = "";
        String temporaryfilename = "";
        String path = "";
        String fieldName = "";
        String title = "";
        String remark = "";
        //4、遍历文件项集合
        for (FileItem fileItem : parseRequest) {
            //5、判断普通表单项/文件上传项
            //是否是一个普通表单项
            boolean formField = fileItem.isFormField();
            if (formField) {
                //普通表单项
                fieldName = fileItem.getFieldName();
                if ("title".equals(fieldName)) {
                    title = new String(fileItem.getString().getBytes("iso8859-1"), StandardCharsets.UTF_8);
                } else if ("remark".equals(fieldName)) {
                    remark = new String(fileItem.getString().getBytes("iso8859-1"), StandardCharsets.UTF_8);
                }
            } else {
                //文件上传项
                //获得上传文件的名称
                fileName = fileItem.getName();
                //提取后缀
                String suffix = fileName.substring(fileName.lastIndexOf("."), fileName.length() - 1);
                //随机的生存一个32的字符串，并加上后缀，生成新文件名
                temporaryfilename = UUID.randomUUID() + suffix;
                //获得上传文件的内容
                InputStream in = fileItem.getInputStream();
                //将in中的数据拷贝服务器上
                path = this.getServletContext().getRealPath("file");
                OutputStream out = new FileOutputStream(path + "/" + temporaryfilename);
                int len = 0;
                byte[] buffer = new byte[1024];
                while ((len = in.read(buffer)) > 0) {
                    out.write(buffer, 0, len);
                }
                in.close();
                out.close();
            }
        }

        //获得参数（因为是form-data，）
        String id = req.getParameter("id");

        //封装对象
        Document_inf document = new Document_inf();
        document.setId(Integer.parseInt(id));
        document.setTitle(title);
        document.setRemark(remark);
        document.setFilename(fileName);
        document.setTemporaryfilename(temporaryfilename);
        document.setFiletype(suffix);
        document.setFilebytes("");
        document.setPath(path);
//        调用service方法
        documentService.updateDocument(document);
        //重定向回去
        resp.sendRedirect(req.getContextPath() + "/documents/findDocumentByPage");
    }

    /**
     * 更新（不更新文件）
     */
    public void updateWithoutDocument(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置编码
        req.setCharacterEncoding("utf-8");
        //获得参数
        Map<String, String[]> map = req.getParameterMap();
        Document_inf document = new Document_inf();
        try {
            //封装
            BeanUtils.populate(document, map);
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
//        调用service方法
        documentService.updateWithoutDocument(document);
        //重定向回去
        resp.sendRedirect(req.getContextPath() + "/documents/findDocumentByPage");
    }

    /**
     * 添加（弃用）
     */
    public void addDocument(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置编码
        req.setCharacterEncoding("utf-8");
        //获得参数
        Map<String, String[]> map = req.getParameterMap();
        //封装对象
        Document_inf document = new Document_inf();
        try {
            BeanUtils.populate(document, map);
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        //调用service保存
        documentService.addDocument(document);
        //跳转到findUserByPage
        resp.sendRedirect(req.getContextPath() + "/documents/toAdd");
    }

    /**
     * 上传文件（含添加）
     */
    public void uploadDocument(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1、创建磁盘文件项工厂
        DiskFileItemFactory factory = new DiskFileItemFactory();
        //2、创建文件上传的核心类
        ServletFileUpload upload = new ServletFileUpload(factory);
        //3、解析request---获得文件项集合
        List<FileItem> parseRequest = new ArrayList<>();
        try {
            parseRequest = upload.parseRequest(req);
        } catch (FileUploadException e) {
            e.printStackTrace();
        }

        String fileName = "";
        String temporaryfilename = "";
        String path = "";
        String fieldName = "";
        String title = "";
        String remark = "";
        //4、遍历文件项集合
        for (FileItem fileItem : parseRequest) {
            //5、判断普通表单项/文件上传项
            //是否是一个普通表单项

            boolean formField = fileItem.isFormField();
            if (formField) {
                //普通表单项
                fieldName = fileItem.getFieldName();
                if ("title".equals(fieldName)) {
                    title = new String(fileItem.getString().getBytes("iso8859-1"), StandardCharsets.UTF_8);
                } else if ("remark".equals(fieldName)) {
                    remark = new String(fileItem.getString().getBytes("iso8859-1"), StandardCharsets.UTF_8);
                }
            } else {
                //文件上传项
                //获得上传文件的名称
                fileName = fileItem.getName();
                //上传到任意位置：调用write(new file(...))即可
                //提取后缀
                String suffix = fileName.substring(fileName.lastIndexOf("."), fileName.length() - 1);
                //随机的生存一个32的字符串，并加上后缀，生成新文件名
                temporaryfilename = UUID.randomUUID() + suffix;
                //获得上传文件的内容
                InputStream in = fileItem.getInputStream();
                //将in中的数据拷贝服务器上
                path = this.getServletContext().getRealPath("file");
                OutputStream out = new FileOutputStream(path + "/" + temporaryfilename);
                int len = 0;
                byte[] buffer = new byte[1024];
                while ((len = in.read(buffer)) > 0) {
                    out.write(buffer, 0, len);
                }
                in.close();
                out.close();
            }
        }

        //封装对象
        Document_inf document = new Document_inf();

        document.setTitle(title);
        document.setRemark(remark);
        document.setFilename(fileName);
        document.setTemporaryfilename(temporaryfilename);
        document.setFiletype(suffix);
        document.setFilebytes("");
        document.setPath(path);
        //得到id
        User_inf user = (User_inf) req.getSession().getAttribute("user");
        document.setUserid(user.getId());
        //调用service保存
        documentService.addDocument(document);

        resp.sendRedirect(req.getContextPath() + "/documents/findDocumentByPage");
    }

    /**
     * 上传（含添加）旧方法
     */
    public void uploadDocument2(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置编码
        req.setCharacterEncoding("utf-8");

        Part part = req.getPart("file");
        String disposition = part.getHeader("Content-Disposition");
        String suffix = disposition.substring(disposition.lastIndexOf("."), disposition.length() - 1);
        String originalfilename = disposition.substring(disposition.lastIndexOf("=") + 2, disposition.length() - 1);
        //随机的生存一个32的字符串
        String filename = UUID.randomUUID() + suffix;
        //获取上传的文件名
        InputStream is = part.getInputStream();
        //动态获取服务器的路径
        String serverpath = req.getServletContext().getRealPath("file");
        FileOutputStream fos = new FileOutputStream(serverpath + "/" + filename);
        byte[] bty = new byte[1024];
        int length = 0;
        while ((length = is.read(bty)) != -1) {
            fos.write(bty, 0, length);
        }
        fos.close();
        is.close();

        //获得参数
        Map<String, String[]> map = req.getParameterMap();
        //解决enctype="multipart/form-data"时中文乱码问题
        Set<String> keySet = map.keySet();
        for (String s : keySet) {
            String[] values = map.get(s);
            for (int i = 0; i < values.length; i++) {
                values[i] = new String(values[i].getBytes("iso8859-1"), StandardCharsets.UTF_8);
            }
        }
        //封装对象
        Document_inf document = new Document_inf();
        try {
            BeanUtils.populate(document, map);
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        document.setFilename(originalfilename);
        document.setTemporaryfilename(filename);
        document.setFiletype(suffix);
        document.setFilebytes(Arrays.toString(bty));
        //得到id
        User_inf user = (User_inf) req.getSession().getAttribute("user");
        document.setUserid(user.getId());
        //调用service保存
        documentService.addDocument(document);

        resp.sendRedirect(req.getContextPath() + "/documents/findDocumentByPage");
    }

    /**
     * 下载
     */
    public void downloadDocument(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //客户端传递的需要下载的id
        String id = req.getParameter("id");
        Document_inf document = documentService.findDocumentById(id);
        ServletContext servletContext = this.getServletContext();
        //默认认为文件在当前项目的根目录
        String path = servletContext.getRealPath("") + "/file/" + document.getTemporaryfilename();
        FileInputStream fis = new FileInputStream(path);

        resp.setCharacterEncoding("utf-8");
        String mimeType = servletContext.getMimeType(document.getFilename());
        resp.setHeader("Content-Type", mimeType);

        //中文编码问题
        String agent = req.getHeader("user-agent");
        String fileName = DownLoadUtils.getFileName(agent, document.getFilename());
        //设置原来的名字
        resp.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        ServletOutputStream out = resp.getOutputStream();
        byte[] bt = new byte[1024];
        int length = 0;
        while ((length = fis.read(bt)) != -1) {
            out.write(bt, 0, length);
        }
        out.close();
    }
}
